﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Spore.SQL
{
    //===========================================================================
    // 表达式计算器
    //===========================================================================
    public class WhereExpressionBuilder
    {
        private readonly Dictionary<string, string> _data =
            new Dictionary<string, string>();

        private SyntaxTreeNode _tree;
        private StringBuilder log;

        //=========================================================================
        // 构造函数
        //   tree: 表达式语法树, 由SyntaxAnalyzer创建;
        //=========================================================================
        private WhereExpressionBuilder(SyntaxTreeNode tree)
        {
            this._tree = tree;
            log = new StringBuilder();
        }

        //=========================================================================
        // 计算表达式值
        public string Process()
        {
            if (_tree == null)
            {
                throw new Exception("计算树为空!");
            }

            log.Remove(0, log.Length);
            return Travel(_tree);
        }

        //=========================================================================
        // 求解过程日志
        //=========================================================================
        public string Log
        {
            get { return log.ToString(); }
        }

        public Dictionary<string, string> Data
        {
            get { return _data; }
        }

        //=========================================================================
        // 遍历表达式分析树,求取结果
        //=========================================================================
        private string Travel(SyntaxTreeNode tree)
        {
            if (tree.Token is Operand)
            {
                //return tree.Token.Value;
                var key = tree.Token.Value;
                if(string.IsNullOrEmpty(key))
                {
                    return "";
                }

                if(Data.ContainsKey(key))
                {
                    return Data[key];
                }

                return "";
            }

            string lsh = tree.LChild == null ? "" : Travel(tree.LChild);
            string rsh = tree.RChild == null ? "" : Travel(tree.RChild);
            return Op(tree.Token.Value, lsh, rsh);
        }


        //=========================================================================
        // 实际计算操作
        //=========================================================================
        private string Op_old(string op, string lsh, string rsh)
        {
            string rslt = "";
            op = op.ToLower();

            if(op == "not")
            {
                rslt = string.Format(" not {0} {1} ", lsh, rsh);
            }
            else if(op == "bracket")
            {
                rslt = string.Format("( {0} {1} )", lsh, rsh);
            }
            else
            {
                rslt = string.Join(" " + op + " ", new string[] { lsh, rsh });
            }


            log.AppendFormat("{0,5}{1,5}{2,5}={3,5}\n", lsh, op, rsh, rslt);
            //return rslt;

            return rslt;
        }

        //=========================================================================
        // 实际计算操作
        //=========================================================================
        private string Op_New(string op, string lsh, string rsh)
        {
            string rslt = "";
            op = op.ToLower();

            string lval = lsh;
            string rval = rsh;

            if (!string.IsNullOrEmpty(lsh))
            {
                if (Data.ContainsKey(lsh))
                {
                    lval = Data[lsh];
                }
            }

            if (!string.IsNullOrEmpty(rsh))
            {
                if (Data.ContainsKey(rsh))
                {
                    rval = Data[rsh];
                }
            }

            if (string.IsNullOrEmpty(lval) && string.IsNullOrEmpty(rval))
            {
                return " ";
            }

            if (op == "not")
            {
                rslt = string.Format(" not {0} {1} ", lval, rval);
            }
            else if (op == "bracket")
            {
                rslt = string.Format("( {0} {1} )", lval, rval);
            }
            else
            {
                if(string.IsNullOrEmpty(lval))
                {
                    rslt = rval;
                }
                else if(string.IsNullOrEmpty(rval))
                {
                    rslt = lval;
                }
                else
                {
                    rslt = string.Join(" " + op + " ", new string[] { lval, rval });
                }
            }


            log.AppendFormat("{0,5}{1,5}{2,5}={3,5}\n", lval, op, rval, rslt);
            return rslt;
        }

        //=========================================================================
        // 实际计算操作
        //=========================================================================
        private string Op(string op, string lsh, string rsh)
        {
            string rslt = "";
            op = op.ToLower();


            if (string.IsNullOrEmpty(lsh) && string.IsNullOrEmpty(rsh))
            {
                return "";
            }

            if (op == "not")
            {
                rslt = string.Format(" not {0} {1} ", lsh, rsh);
            }
            else if (op == "bracket")
            {
                rslt = string.Format("( {0} {1} )", lsh, rsh);
            }
            else
            {
                if(string.IsNullOrEmpty(lsh))
                {
                    rslt = rsh;
                }
                else if(string.IsNullOrEmpty(rsh))
                {
                    rslt = lsh;
                }
                else
                {
                    rslt = string.Join(" " + op + " ", new string[] { lsh, rsh });
                }
            }


            log.AppendFormat("{0,5}{1,5}{2,5}={3,5}\n", lsh, op, rsh, rslt);
            return rslt + Environment.NewLine;
        }

        public static WhereExpressionBuilder New(string input)
        {
            var ga = new GrammarAnalyzer(input);
            ga.Analyze();

            Token[] toks = ga.TokenList;
            //for (int i = 0; i < toks.Length; ++i)
            //{
            //    Console.WriteLine(toks[i]);
            //}

            var sa = new SyntaxAnalyzer(toks);
            sa.Analyze();


            var calc = new WhereExpressionBuilder(sa.SyntaxTree);

            return calc;
        }
    }
}
